package org.jader.bolao;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.jader.bolao.beans.PropertyChanger;

public class GameIndividual extends PropertyChanger implements Game {

	private Championship owner = null;
	
	private long timestamp = 0;
	private String place = "";
	private Date date = null;
	private List<GamePlayer> players = new LinkedList<GamePlayer>();
	
	protected GameIndividual(Championship c) {
		this.owner = c;
		this.timestamp = System.currentTimeMillis();
	}
	
	public String toString() {
		String s;
		
		if (date != null) s = new SimpleDateFormat("dd.MM.yyyy").format(date);
		else s = "{No date}";
		
		if (place.length() > 0)	s += " - " + place;
		else s += " - {No place}";
		
		return s;
	}
	
	public Championship championship() {
		return this.owner;
	}

	public String getPlace() {
		return this.place;
	}
	
	public void setPlace(String p) {
		if (this.place != null && this.place.compareTo(p) == 0) return;
		this.place = p;
		this.firePropertyChange(this, "place");
	}
	
	public Date getDate() {
		return this.date;
	}
	
	public void setDate(Date d) {
		if (this.date != null && this.date.compareTo(d) == 0) return;
		this.date = d;
		this.firePropertyChange(this, "date");
	}
	
	public void addPlayer(int arg0, Player arg1) {
		players.add(arg0, new GamePlayer(this, arg1));
		this.firePropertyChange(this, "players");
	}

	public boolean addPlayer(Player arg0) {
		boolean result = players.add(new GamePlayer(this, arg0));
		if (result) this.firePropertyChange(this, "players");
		return result;
	}

	public boolean addPlayers(Collection<? extends Player> arg0) {
		Collection<GamePlayer> list = new ArrayList<GamePlayer>();
		Iterator<? extends Player> it = arg0.iterator();
		while (it.hasNext()) list.add(new GamePlayer(this, it.next()));
		boolean result = players.addAll(list);
		if (result) this.firePropertyChange(this, "players");
		return result;
	}

	public boolean addPlayers(int arg0, Collection<? extends Player> arg1) {
		Collection<GamePlayer> list = new ArrayList<GamePlayer>();
		Iterator<? extends Player> it = arg1.iterator();
		while (it.hasNext()) list.add(new GamePlayer(this, it.next()));
		boolean result = players.addAll(arg0, list);
		if (result) this.firePropertyChange(this, "players");
		return result;
	}

	public void clearPlayers() {
		players.clear();
		this.firePropertyChange(this, "players");
	}

	public boolean containsPlayer(Object arg0) {
		if (arg0 instanceof Player){
			Iterator<GamePlayer> it = players.iterator();
			while (it.hasNext()) {
				if (it.next().player().equals(arg0)) return true;
			}
			return false;
		}
		else
			return players.contains(arg0);
	}

	public boolean containsPlayers(Collection<?> arg0) {
		return players.containsAll(arg0);
	}

	public GamePlayer getPlayer(int arg0) {
		return players.get(arg0);
	}

	public GamePlayer getPlayer(Player arg0) {
		for (int index=0; index<players.size(); index++) {
			if (players.get(index).player().equals(arg0))
				return players.get(index);
		}
		return null;
	}

	public int indexOfPlayer(Object arg0) {
		if (arg0 instanceof Player){
			for (int index=0; index<players.size(); index++) {
				if (players.get(index).player().equals(arg0))
					return index;
			}
			return -1;
		}
		else
			return players.indexOf(arg0);
	}

	public boolean hasNoPlayer() {
		return players.isEmpty();
	}

	public Iterator<GamePlayer> playerIterator() {
		return players.iterator();
	}

	public GamePlayer removePlayer(int arg0) {
		GamePlayer result = players.remove(arg0);
		if (result != null) this.firePropertyChange(this, "players");
		return result;
	}

	public boolean removePlayer(GamePlayer p) {
		boolean result = players.remove(p);
		if (result)  this.firePropertyChange(this, "players");
		return result;
	}

	public boolean removePlayers(Collection<?> arg0) {
		boolean result = players.removeAll(arg0);
		if (result)  this.firePropertyChange(this, "players");
		return result;
	}

	public void swapPlayers(GamePlayer a, GamePlayer b) {
		if (!players.contains(a) || !players.contains(b)) return;
		if (a.equals(b)) return;
		int indexA = players.indexOf(a);
		int indexB = players.indexOf(b);
		players.set(indexA, b);
		players.set(indexB, a);
		this.firePropertyChange(this, "players");
	}

	public int numberOfPlayers() {
		return players.size();
	}

	public List<GamePlayer> subListOfPlayers(int arg0, int arg1) {
		return players.subList(arg0, arg1);
	}
	
	public List<GamePlayer> subListOfPlayers(Team arg0) {
		List<GamePlayer> subList = new ArrayList<GamePlayer>();
		Iterator<GamePlayer> it = players.iterator();
		while (it.hasNext()) {
			GamePlayer p = it.next();
			if (p.player().team().equals(arg0))
				subList.add(p);
		}
		return subList;
	}

	public HashSet<Player> availablePlayers() {
		HashSet<Player> players = new HashSet<Player>();
		Iterator<Team> itt = owner.teamsIterator();
		while (itt.hasNext()) {
			Iterator<Player> itp = itt.next().playerIterator();
			while (itp.hasNext()) players.add(itp.next());
		}
		return players;
	}

	@Override
	public int compareTo(Game g) {
		if (this.date != null && g.getDate() != null) return this.date.compareTo(g.getDate());
		if (g instanceof GameIndividual) {
			GameIndividual gi = (GameIndividual) g;
			if (this.timestamp < gi.timestamp) return -1;
			if (this.timestamp > gi.timestamp) return 1;
		}
		return 0;
	}
	
	@Override
	public void refreshPropertyChangeListeners() {
		if (this.owner == null) return;
		this.addPropertyChangeListener(this.owner);
	}

	@Override
	public boolean containsTeam(Object arg0) {
		Iterator<GamePlayer> it = players.iterator();
		while (it.hasNext()) {
			if (it.next().player().team().equals(arg0))
				return true;
		}
		return false;
	}

	@Override
	public Iterator<Team> teamsIterator() {
		HashSet<Team> teams = new HashSet<Team>();
		Iterator<GamePlayer> it = players.iterator();
		while (it.hasNext()) teams.add(it.next().player().team());
		return teams.iterator();
	}
}
